package Net::BitTorrent::Tracker;

use warnings;
use strict;
use Carp qw(croak);
use Convert::Bencode qw(bdecode);
use LWP::Simple;
use URI;

sub new {
    my ( $class, %self ) = @_;

    for (qw(tracker info_hash peer_id port)) {
        croak("$_ required") unless exists $self{$_};
    }

    $self{event} = 'started' unless exists $self{event};

    bless \%self, $class;

    return \%self;
}

sub get_more_peers {
    my ($self) = @_;

    my $uri = URI->new( $self->{tracker} );
    $uri->query_form(
        {
            info_hash => $self->{info_hash},
            peer_id   => $self->{peer_id},
            port      => $self->{port},
            event     => $self->{event},
        }
    );

    $self->{event} = 'empty';

    my $content = get( $uri->as_string() );

    return unless $content;

    my $response = bdecode($content);

    return $response->{'failure reason'}
      if exists $response->{'failure reason'};

    return $response->{peers} || '';
}

1;

__END__

=pod

=head1 NAME

Net::BitTorrent::Tracker

=head1 DESCRIPTION

The C<Net::BitTorrent::Tracker> is an interface to a tracker object for
a swarm.  The tracker coordinates the swarm by telling the peers about
each other.  This is a very loose form of cooridnation... basically, the
traker returns a list of peers each time it is pinged and leaves it up
to the client to determine which of the peers it wants to associate with.

=head1 SYNOPSYS

    my $tracker = Net::BitTorrent::Tracker->new(
        tracker   => "http://${host}:${port}/track",
        port      => $port,
        info_hash => 'A' x 20,
        peer_id   => 'B' x 20,
        ip => inet_ntoa( scalar gethostbyname( hostname() || 'localhost' ) ),
    );
    
    my @peers = $tracker->get_more_peers()
    
    for my $peer (@peers) {
        print join("\n", $peer->{'peer id'}, $peer->{ip}, $peer->{port}), "\n");
    }

=head1 METHODS

=head2 new

=head3 Parameters

=head4 tracker

This is the URL of the tracker that is managing the specific torrent.  This
should be in the 'http://domain:port/path/to/tracker' format so that an easy
GET request can be made to the tracker.  Lucky for us, this is the way that
the tracker is packaged in the C<.torrent> file, so really this is just a
pass-through field from there.

=head4 info_hash [required]

This is the 20-byte sha1 hash for the torrent that is found in the metainfo,
a.k.a. C<.torrent> file.

=head4 peer_id [required]

This is a 20-byte ID that is generated by the local torrent program that is
used to identify the peer.

=head4 port [required]

Port that this peer is listening on for connections from other peers.

=head4 ip

IP address or DNS name for the local peer.

=head4 uploaded

Total amount of data uploaded so far.  This is intended to be representative
of the current downloading session and is meant to be reset when a torrent
is resumed.

=head4 downloaded

Total amount of data downloaded so far.  This is intended to be representative
of the current downloading session and is meant to be reset when a torrent
is resumed.

=head4 left

How much of the torrent file is left to be downloaded?

=head4 event

A keyword sent to the tracker to signfy status:

=over 4

=item * started

Sent when the downlaod first begins (or resumes).

=item * completed (unimplemented)

Sent when downloading is complete.

=item * stopped (unimplemented)

Sent when leaving the torrent.

=item * empty

Default when no C<left> argument is present.  This signifies a keep-alive.

=back

=cut


